release: v10.17.0 — J2KDICOMHelpers Phase 1 (new SwiftPM product)#453
Merged
Conversation
Ships a new public J2KDICOMHelpers library that bridges DICOM Transfer
Syntax UIDs to J2KEncodingConfiguration. Closes a long-standing product-
layer gap: library consumers using their own DICOM parser (DICOMKit,
pydicom-via-XPC, etc.) get a Transfer Syntax UID + Pixel Data bytes, and
previously had to hand-roll the UID-to-config mapping.
Per ADR-004, J2KSwift core libraries don't depend on any DICOM library.
The CLI ships a DICOMSupport.swift for .dcm file loading, but the
DICOMTransferSyntax / DICOMTransferSyntaxInfo types there are CLI-private
— not surfaced to library consumers. v10.17.0 lifts the UID-bridge layer
into a new public SwiftPM library.
Public surface:
* J2KDICOMTransferSyntax — CaseIterable enum over all 7 DICOM Part 5
Annex A JPEG 2000 / HTJ2K UIDs (j2kLossless 90, j2kLossy 91,
j2kPart2MulticompLossless 92, j2kPart2Multicomp 93, htj2kLossless 201,
htj2kLossyConstant 202, htj2kLossy 203). init?(uid:) / var uid round-trip
(whitespace + trailing-NUL tolerant per PS3.5 §6.2). isLossless /
isHTJ2K / isPart2 classification flags.
* J2KDICOMTransferSyntax.encodingConfiguration(bitDepth:psnrTarget:) —
returns matching J2KEncodingConfiguration with htj2kBlockFormat:
.conformant for DICOM interop.
* J2KDICOMCodestreamDetector.detect(_:) — sniffs SOC + (optional) CAP
markers in the first ~256 bytes to classify raw codestreams as
.j2kLossless (Part 1, no CAP) or .htj2kLossless (Part 15, CAP present).
Returns nil for non-J2K bytes (JPEG SOI, PNG sig, random bytes all
correctly reject).
* J2KDICOMPhotometricInterpretation — enum mirror of the 7 DICOM
PhotometricInterpretation values relevant to J2K. Bidirectional
J2KColorSpace mapping (greyscale ↔ MONOCHROME2, sRGB ↔ RGB,
yCbCr ↔ YBR_FULL; hdr/hdrLinear/iccProfile/unknown return nil
in reverse).
ADR-004 compliant: no DICOM library dependency anywhere in J2KSwift —
the new product depends only on J2KCore + J2KCodec. Consumers not
importing J2KDICOMHelpers are completely unaffected.
Phase 1 deliberately ships the smallest viable shape — UID-and-config
bridge only. Phase 2 (likely v10.18+) would extract more of
J2KCLI/DICOMSupport.swift's file-parsing logic or ship a DICOMKit
adapter as a sibling opt-in product.
AsyncSequence progress streams (originally Phase 3 of the v10.17.0
plan) deferred to a dedicated MINOR — the AsyncStream-vs-actor-stored-
callback lifecycle has subtle correctness questions that warrant a
focused ship rather than being squeezed in.
Validation:
- V10_29_TransferSyntaxRoundTripTests 9/9 PASS
- V10_29_EncodingConfigurationParityTests 5/5 PASS (incl. bit-exact
lossless round-trip via helper-built configs)
- V10_29_CodestreamDetectionTests 6/6 PASS
- V10_29_PhotometricInterpretationTests 6/6 PASS
- V10_29 total: 26/26 PASS release mode
- swift test --filter JP3D regression 528/528 PASS (1 pre-existing skip)
- Mandatory commit gate (release mode) 7/7 PASS
MINOR per RELEASING.md — entirely additive: new product, zero touch to
existing libraries, codestream bytes byte-identical to v10.16.0, no
DICOM library dependency added anywhere. Also bumps getVersion()
constant 10.16.0 → 10.17.0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
J2KEncodingConfiguration. Closes a long-standing product-layer gap: library consumers parsing DICOM with their own library (DICOMKit, pydicom-via-XPC, etc.) get a Transfer Syntax UID + Pixel Data bytes, and previously had to hand-roll the UID-to-config mapping.J2KCore+J2KCodec. Consumers not importingJ2KDICOMHelpersare completely unaffected.Public surface added
J2KDICOMTransferSyntaxenum (7 cases)J2KDICOMTransferSyntax.encodingConfiguration(bitDepth:psnrTarget:)J2KEncodingConfigurationwithhtj2kBlockFormat: .conformantfor DICOM interopJ2KDICOMCodestreamDetector.detect(_:).j2kLossless/.htj2kLossless; returns nil for non-J2K bytesJ2KDICOMPhotometricInterpretationenum (7 cases)J2KColorSpacemappingCorrectness gate (release mode)
V10_29_TransferSyntaxRoundTripTests9/9 PASSV10_29_EncodingConfigurationParityTests5/5 PASS (incl. bit-exact lossless round-trip)V10_29_CodestreamDetectionTests6/6 PASSV10_29_PhotometricInterpretationTests6/6 PASSswift test --filter JP3Dregression 528/528 PASS (1 pre-existing skip)J2KMedicalCorpusEncodePerformanceTests2/2 PASSJ2KMedicalCorpusPerformanceTests2/2 PASSJ2KStrictCrossCodecValidationTests3/3 PASSMandatory commit gate: 7/7 PASS release mode.
Phase 1 scope discipline
Phase 1 deliberately ships the smallest viable shape — UID-and-config bridge only. Phase 2 (likely v10.18+) would extract more of
J2KCLI/DICOMSupport.swift's file-parsing logic or ship a DICOMKit adapter as a sibling opt-in product. AsyncSequence progress streams (originally Phase 3 of the v10.17.0 plan) deferred to a dedicated MINOR — the AsyncStream-vs-actor-stored-callback lifecycle has subtle correctness questions that warrant a focused ship rather than being squeezed in.Test plan
getVersion()bumped 10.16.0 → 10.17.0J2KDICOMHelpers+ target + test target🤖 Generated with Claude Code